﻿using System;
using System.Collections.ObjectModel;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using Hutech.Authentication.Library.Data;
using log4net;

namespace Hutech.Authentication.Library.Business
{
    public class Role
    {
        /// <summary>
        /// Lop mo ta cau truc va cac xu ly cua doi tuong Site.
        /// Author:         tsandtm
        /// Created Date:   24/03/2010
        /// </summary>
        #region Constructors
        public Role()
        {
        }

        public Role(Guid roleId)
        {
            GetRole(roleId);
        }

        public Role(string roleName)
        {
            GetRole(roleName);
        }

        #endregion

        #region Private Properties

        private static readonly ILog log = LogManager.GetLogger(typeof(Role));

        private Guid roleId = Guid.Empty;
        private string roleName = string.Empty;
        private string displayName = string.Empty;
        private Guid siteID = Guid.Empty;

        #endregion

        #region Public Properties
        public Guid SiteID
        {
            get
            {
                return siteID;
            }
            set
            {
                siteID = value;
            }
        }
        public Guid RoleId
        {
            get
            {
                return roleId;
            }
        }


        public string RoleName
        {
            get
            {
                return displayName;
            }
            set
            {
                displayName = value;
            }
        }

        public string DisplayName
        {
            get
            {
                return displayName;
            }
        }

        private int memberCount = 0;
        /// <summary>
        /// this is only populated when calling GetbySite
        /// </summary>
        public int MemberCount
        {
            get
            {
                return memberCount;
            }
        }
        #endregion


        #region Private Methods

        private void GetRole(Guid roleId)
        {
            using (IDataReader reader = DBRole.GetById(roleId))
            {
                if (reader.Read())
                {
                    this.roleId = new Guid(reader["RoleId"].ToString());
                    this.roleName = reader["RoleName"].ToString();
                    this.displayName = reader["DisplayName"].ToString();
                    this.siteID = new Guid(reader["SiteId"].ToString());
                }
            }
        }

        private void GetRole(string roleName)
        {
            using (IDataReader reader = DBRole.GetByName(roleName))
            {
                if (reader.Read())
                {
                    this.roleId = new Guid(reader["RoleId"].ToString());
                    this.roleName = reader["RoleName"].ToString();
                    this.displayName = reader["DisplayName"].ToString();
                    this.siteID = new Guid(reader["SiteId"].ToString());
                }
            }
        }

        private bool Create()
        {
            bool result = false;
            // role name never changes after creation
            // only display name is allowed to change
            // otherwise permissions to view pages 
            // and edit modules would be orphaned when
            // a role was re-named
            if (Exists(this.displayName))
            {
                //string errorMessage = ConfigurationManager.AppSettings["RoleExistsError"];
                //throw new Exception(errorMessage);
                // do nothing instead of  throwing an exception

            }
            else
            {
                this.roleId = Guid.NewGuid();

                result = DBRole.RoleCreate(
                this.roleId,
                this.siteID,
                this.displayName);
            }

            if (result)
            {
                this.roleName = this.displayName;
                return true;
            }
            else
            {
                return false;
            }
        }

        private bool Update()
        {
            return DBRole.Update(this.roleId, this.displayName);
        }

        public bool Equals(string roleName)
        {
            bool result = false;
            if (roleName == this.roleName)
                result = true;

            return result;
        }

        #endregion


        #region Public Methods



        public bool Save()
        {
            if (this.roleId != Guid.Empty)
            {
                return Update();
            }
            else
            {
                return Create();
            }
        }

        public bool HasUsers()
        {
            return (CountOfUsers() > 0);
        }

        public int CountOfUsers()
        {
            // TODO: implement actual select count from db
            // this is works but is not ideal
            int count = 0;
            using (IDataReader reader = GetRoleMembers(this.roleId))
            {
                while (reader.Read())
                {
                    count += 1;
                }
            }

            return count;
        }



        #endregion

        #region Static Methods

        public static IDataReader GetSiteRoles()
        {
            return DBRole.GetSiteRoles();
        }

        public static List<Role> GetbySite()
        {
            List<Role> roles = new List<Role>();
            using (IDataReader reader = DBRole.GetSiteRoles())
            {
                while (reader.Read())
                {
                    Role role = new Role();
                    role.roleId = new Guid(reader["RoleId"].ToString());
                    role.displayName = reader["DisplayName"].ToString();
                    role.roleName = reader["RoleName"].ToString();
                    role.memberCount = Convert.ToInt32(reader["MemberCount"]);
                    roles.Add(role);
                }
            }

            return roles;
        }

        public static Role GetRoleByName(string roleName)
        {
            Role role = null;

            using (IDataReader reader = DBRole.GetSiteRoles())
            {
                while (reader.Read())
                {
                    string foundName = reader["RoleName"].ToString();
                    if (foundName == roleName)
                    {
                        role = new Role();
                        role.roleId = new Guid(reader["RoleId"].ToString());
                        role.displayName = reader["DisplayName"].ToString();
                        role.roleName = reader["RoleName"].ToString();
                    }
                }
            }

            return role;
        }

        public static List<Guid> GetRoleIds(string roleNamesSeparatedBySemiColons)
        {
            List<Guid> roleIds = new List<Guid>();

            List<string> roleNames = GetRolesNames(roleNamesSeparatedBySemiColons);

            foreach (string roleName in roleNames)
            {
                if (string.IsNullOrEmpty(roleName))
                {
                    continue;
                }
                Role r = Role.GetRoleByName(roleName);
                if (r == null)
                {
                    //log.Debug("could not get roleid for role named " + roleName);
                    continue;
                }
                if (r.RoleId != Guid.Empty)
                {
                    roleIds.Add(r.RoleId);
                }
            }

            return roleIds;
        }

        public static List<string> GetRolesNames(string roleNamesSeparatedBySemiColons)
        {
            List<string> roleNames = new List<string>();
            string[] roles = roleNamesSeparatedBySemiColons.Split(';');
            foreach (string r in roles)
            {
                if (!roleNames.Contains(r))
                {
                    roleNames.Add(r);
                }
            }

            return roleNames;
        }

        public static int CountRoleByUser(Guid UserID)
        {
            // TODO: implement actual select count from db
            // this is works but is not ideal
            int count = 0;

            using (IDataReader reader = DBRole.GetRolesOfUser(UserID))
            {
                while (reader.Read())
                {
                    count += 1;
                }
            }
            return count;
        }

        public static int CountOfRoles()
        {
            // TODO: implement actual select count from db
            // this is works but is not ideal
            int count = 0;
            using (IDataReader reader = GetSiteRoles())
            {
                while (reader.Read())
                {
                    count += 1;
                }
            }

            return count;
        }

        public static bool DeleteRole(Guid roleId)
        {
            return DBRole.Delete(roleId);
        }

        public static bool Exists(String roleName)
        {
            //if (UseRelatedSiteMode) { siteId = RelatedSiteId; }
            return DBRole.Exists(roleName);
        }

        public static IDataReader GetRoleMembers(Guid roleId)
        {
            return DBRole.GetRoleMembers(roleId);
        }

        public static IDataReader GetUsersNotInRole(Guid roleId)
        {
            return DBRole.GetUsersNotInRole(roleId);
        }

        public static IDataReader GetRolesUserIsNotIn(
        Guid userId)
        {
            return DBRole.GetRolesUserIsNotIn(
            userId);
        }

        public static bool AddUser(Guid roleId, Guid userId)
        {
            return DBRole.AddUser(roleId, userId);
        }

        public static bool RemoveUser(Guid roleId, Guid userId)
        {
            return DBRole.RemoveUser(roleId, userId);
        }

        public static bool DeleteUserRoles(Guid userId)
        {
            return DBRole.DeleteUserRoles(userId);
        }

        public static void AddUserToDefaultRoles(SiteUser siteUser)
        {
            Role role = new Role("ChuaXacDinh");
            if (role.RoleId != Guid.Empty)
            {
                Role.AddUser(role.RoleId, siteUser.UserId);
            }
        }
        public static bool ChangeUserToNotAuthenticated(Guid _userID)
        {
            Role role = new Role("ChuaXacDinh");
            if (role.RoleId!=Guid.Empty)
            {
                return DBUserRoles.Update(_userID, role.RoleId);
            }
            return false;
        }
        #endregion

        public static bool CheckRoleAuthenticatedByUserID(Guid _UserID)
        {
            Role role = new Role("ChuaXacDinh");
            return DBUserRoles.CheckRoleAuthenticatedByUserID(_UserID, role.RoleId);
        }

        public static IDataReader GetRoleNotInModule(Guid ModuleID)
        {
            return DBRole.GetRoleNotInModule(ModuleID);
        }

        public static bool DeleteAllRoleOfUser(Guid userID)
        {
            return DBUserRoles.DeleteAllRoleOfUser(userID);
        }


    }
}
